from io import StringIO

import datetime
import streamlit as st
import pandas as pd
import plotly.express as px
import numpy as np

import time
import math
import plotly.graph_objects as go

st.set_page_config(
    page_title="储能收益计算系统",
    page_icon="🔋",
    layout="wide"
)

# sidebar_logo = 'logo_hb.png'
# main_body_logo = 'logo_hb.png'
# st.logo(sidebar_logo, link='http://www.crcept.com/', icon_image=main_body_logo)


def calculate_count(time):
    from datetime import datetime, time as dt_time
    # 从00:15开始计数为1
    start_time = dt_time(0, 15)
    # 计算时间差（以分钟为单位）
    minutes_diff = (time.hour * 60 + time.minute) - (start_time.hour * 60 + start_time.minute)
    # 每15分钟为一个单位
    return (minutes_diff // 15) + 1


def max_profit(prices, capacity):
    prices = prices.reset_index(drop=True)
    n = len(prices)  # 时间点数量
    dp = np.zeros((n + 1, capacity + 1))
    traceback = -np.ones((n + 1, capacity + 1), dtype=int)
    idle, charge, discharge = 0, 1, 2
    investment = 0
    for j in range(capacity - 1, -1, -1):
        investment = investment - prices[node][capacity - j] * reserve_capacity / capacity
        dp[0][j] = investment

    progress_text = "计算最佳方案中，请稍后。"
    my_bar = st.progress(0, text=progress_text)
    # 动态规划转移方程
    for i in range(1, n + 1):
        for j in range(capacity + 1):
            # 不进行充放电，直接从上一个状态继承最大收益
            dp[i][j] = dp[i - 1][j]
            traceback[i][j] = idle

            # 如果可以充电并且剩余容量允许
            if j < capacity:
                potential_gain_charge = dp[i - 1][j + 1] - (prices[area][i - 1]) * reserve_capacity / capacity
                if potential_gain_charge > dp[i][j]:
                    dp[i][j] = potential_gain_charge
                    traceback[i][j] = charge

            # 如果可以放电并且当前有电可放
            if j > 0:
                potential_gain_discharge = dp[i - 1][j - 1] + (
                    prices[node][i - 1]) * reserve_capacity * efficiency / capacity - (
                                                   reserve_capacity / capacity * others * 1000)
                if potential_gain_discharge > dp[i][j]:
                    dp[i][j] = potential_gain_discharge
                    traceback[i][j] = discharge
        if i % (int(n / 100) + 1) == 0:
            my_bar.progress(int(i / (n / 100)), text=progress_text)
    my_bar.progress(100, text="计算完成")
    time.sleep(1)
    my_bar.empty()
    i, j = n, capacity  # 从最后一个时间点和最大容量开始回溯
    operations_sequence = []  # 用于存储操作序列
    while i > 0:
        operation = traceback[i][j]
        if operation == charge:
            operations_sequence.append(charge)
        elif operation == discharge:
            operations_sequence.append(discharge)
        else:  # idle
            operations_sequence.append(idle)

        # 根据操作更新i和j的值以进行下一步回溯
        if operation == charge:
            j += 1  # 如果是充电，则容量增加
        elif operation == discharge:
            j -= 1  # 如果是放电，则容量减少

        i -= 1  # 总是向之前的时间点移动

    # 由于序列是反向生成的（从结束到开始），我们需要将其反转以符合时间顺序
    operations_sequence.reverse()
    return max(dp[n]), operations_sequence  # 返回最大收益和操作序列


def max_profit_more(prices, capacity):
    cooldown = capacity
    prices = prices.reset_index(drop=True)
    n = len(prices)  # 时间点数量
    dp = np.zeros((n + 1, 2))
    traceback = -np.ones((n + 1, 2), dtype=int)
    idle, charge, discharge = 0, 1, 2

    def price(i, o):
        average_price = 0
        for k in range(capacity):
            if i < n - capacity:
                average_price += prices[o][i - 1 + k]
        return average_price / capacity

    dp[0][0] = - prices[node][1] * reserve_capacity

    # 动态规划转移方程
    for i in range(1, n + 1):
        cooldown -= 1  # 每次迭代减少冷却计数器

        for j in [0, 1]:
            dp[i][j] = dp[i - 1][j]
            traceback[i][j] = idle

            # 跳过冷却期内的充放电操作
            if cooldown > 0:
                continue

            # 如果可以充电并且剩余容量允许
            if j < 1:
                potential_gain_charge = dp[i - 1][j + 1] - price(i, area) * reserve_capacity
                if potential_gain_charge > dp[i][j]:
                    dp[i][j] = potential_gain_charge
                    traceback[i][j] = charge
                    cooldown = capacity  # 充电后重置冷却计数器

            # 如果可以放电并且当前有电可放
            if j > 0:
                potential_gain_discharge = dp[i - 1][j - 1] + (
                    price(i, node)) * reserve_capacity * efficiency - (
                                                   reserve_capacity * others * 1000)
                if potential_gain_discharge > dp[i][j]:
                    dp[i][j] = potential_gain_discharge
                    traceback[i][j] = discharge
                    cooldown = capacity  # 放电后重置冷却计数器

    i, j = n, 1  # 从最后一个时间点和最大容量开始回溯
    operations_sequence = []  # 用于存储操作序列
    while i > 0:
        operation = traceback[i][j]
        if operation == charge:
            operations_sequence.append(charge)
        elif operation == discharge:
            operations_sequence.append(discharge)
        else:  # idle
            operations_sequence.append(idle)

        # 根据操作更新i和j的值以进行下一步回溯
        if operation == charge:
            j += 1  # 如果是充电，则容量增加
        elif operation == discharge:
            j -= 1  # 如果是放电，则容量减少

        i -= 1  # 总是向之前的时间点移动
    # 由于序列是反向生成的（从结束到开始），我们需要将其反转以符合时间顺序
    operations_sequence.reverse()
    return max(dp[n]), operations_sequence  # 返回最大收益和操作序列


def calculate_daily_gain(energy, group, time_1, time_2, time_3, time_4, time_5, time_6, time_7):
    max_gain = 0
    energy_time = 0
    prices = group.reset_index(drop=True)
    date_values = prices["日期"][0].date()
    area_values = group[area].values
    area_date = group["日期+时刻"].values
    node_values = group[node].values
    node_date = group["日期+时刻"].values
    min_start_index = 0
    max_start_index = 0
    for op in range(1, energy + 1):
        min_sum = float('inf')
        min_index = 0
        for i in range(len(area_values) - op - 1):  # 减15是因为窗口大小为16
            current_sum = sum(area_values[i:i + op])
            if current_sum < min_sum:
                min_sum = current_sum
                min_index = i
        min_sum = min_sum / op

        max_sum = 0
        max_index = 0
        for i in range(min_index + op, len(node_values) - op - 1):  # 减15是因为窗口大小为16
            current_sum = sum(node_values[i:i + op])
            if current_sum > max_sum:
                max_sum = current_sum
                max_index = i
        max_sum = max_sum / op

        daily_gain = reserve_speed / 4 * op * efficiency * max_sum - reserve_speed / 4 * op * min_sum - reserve_speed / 4 * op * others * 1000
        if daily_gain > max_gain:
            max_gain = daily_gain
            max_start_index = max_index
            min_start_index = min_index
            energy_time = op

    for i in range(energy_time):
        time_4.append(area_date[min_start_index + i])
        time_5.append(area_values[min_start_index + i])
        time_6.append(node_date[max_start_index + i])
        time_7.append(node_values[max_start_index + i])

    if max_gain > 0:
        time_1.append(date_values)
        time_2.append(energy_time * reserve_speed / 4 * efficiency)
        time_3.append(energy_time * reserve_speed / 4)
        return max_gain
    else:
        time_1.append(date_values)
        time_2.append(0)
        time_3.append(0)
        return 0


def max_daily_profit(prices, capacity, op, time_1, time_2, time_3, time_4, time_5, time_6, time_7, time_8):
    # time_2.clear()
    # time_1.clear()
    prices = prices.reset_index(drop=True)
    daily_profit = 0
    charge_time = 0
    discharge_time = 0
    date_values = prices["日期"][0].date()
    for i in range(len(prices)):
        if prices[op][i] == 1:
            daily_profit -= prices[area][i] * reserve_capacity / capacity
            charge_time += 1
            time_4.append(prices["日期+时刻"][i])
            time_5.append(prices[area][i])
        elif prices[op][i] == 2:
            daily_profit += prices[node][i] * reserve_capacity * efficiency / capacity - (
                    reserve_capacity / capacity * others * 1000)
            discharge_time += 1
            time_6.append(prices["日期+时刻"][i])
            time_7.append(prices[node][i])
        # elif prices[op][i] == 0:
        # charge_discharge_time.append(f'{prices["日期+时刻"][i]} 空闲：15分钟')
    time_8.append(f'充电{charge_time}次，放电{discharge_time}次')
    time_1.append(date_values)
    time_2.append(discharge_time * reserve_capacity * efficiency / capacity)
    time_3.append(charge_time * reserve_capacity / capacity)
    return daily_profit


st.title('Uber pickups in NYC')
with st.container(border=True):
    st.write('光伏')
    uploaded_files = st.file_uploader(
        "光伏第0年每小时发电量（KWh）", accept_multiple_files=True
    )
    for uploaded_file in uploaded_files:
        stringio = StringIO(uploaded_file.getvalue().decode("utf-8"))
        pv_hourly_generation_year_0 = pd.read_csv(uploaded_file)
        st.write(pv_hourly_generation_year_0)

    col1, col2 = st.columns(2)
    with col1:
        first_year_decay = st.number_input("光伏组件首年衰减%") / 100
    with col2:
        multi_year_decay = st.number_input("光伏组件2-25年衰减%") / 100

with st.container(border=True):
    st.write('工商业负荷')
    tab1, tab2, tab3, tab4 = st.tabs(["年", "季", "月", "日"])
    with tab1:
        uploaded_files = st.file_uploader(
            "按年", accept_multiple_files=True, label_visibility='collapsed'
        )
        for uploaded_file in uploaded_files:
            stringio = StringIO(uploaded_file.getvalue().decode("utf-8"))
            business_load = pd.read_csv(uploaded_file)
            st.write(business_load)

    with tab2:
        uploaded_files = st.file_uploader(
            "按季", accept_multiple_files=True, label_visibility='collapsed'
        )
        for uploaded_file in uploaded_files:
            stringio = StringIO(uploaded_file.getvalue().decode("utf-8"))
            business_load = pd.read_csv(uploaded_file)
            st.write(business_load)

    with tab3:
        uploaded_files = st.file_uploader(
            "按月", accept_multiple_files=True, label_visibility='collapsed'
        )
        for uploaded_file in uploaded_files:
            stringio = StringIO(uploaded_file.getvalue().decode("utf-8"))
            business_load = pd.read_csv(uploaded_file)
            st.write(business_load)

    with tab4:
        uploaded_files = st.file_uploader(
            "按天", accept_multiple_files=True, label_visibility='collapsed'
        )
        for uploaded_file in uploaded_files:
            stringio = StringIO(uploaded_file.getvalue().decode("utf-8"))
            business_load = pd.read_csv(uploaded_file)
            st.write(business_load)

with st.container(border=True):
    st.write('充电桩负荷')
    tab1, tab2, tab3, tab4 = st.tabs(["年", "季", "月", "日"])
    with tab1:
        uploaded_files = st.file_uploader(
            "充电桩按年", accept_multiple_files=True, label_visibility='collapsed'
        )
        for uploaded_file in uploaded_files:
            stringio = StringIO(uploaded_file.getvalue().decode("utf-8"))
            charging_station_load = pd.read_csv(uploaded_file)
            st.write(charging_station_load)

    with tab2:
        uploaded_files = st.file_uploader(
            "充电桩按季", accept_multiple_files=True, label_visibility='collapsed'
        )
        for uploaded_file in uploaded_files:
            stringio = StringIO(uploaded_file.getvalue().decode("utf-8"))
            charging_station_load = pd.read_csv(uploaded_file)
            st.write(charging_station_load)

    with tab3:
        uploaded_files = st.file_uploader(
            "充电桩按月", accept_multiple_files=True, label_visibility='collapsed'
        )
        for uploaded_file in uploaded_files:
            stringio = StringIO(uploaded_file.getvalue().decode("utf-8"))
            charging_station_load = pd.read_csv(uploaded_file)
            st.write(charging_station_load)

    with tab4:
        uploaded_files = st.file_uploader(
            "充电桩按天", accept_multiple_files=True, label_visibility='collapsed'
        )
        for uploaded_file in uploaded_files:
            stringio = StringIO(uploaded_file.getvalue().decode("utf-8"))
            charging_station_load = pd.read_csv(uploaded_file)
            st.write(charging_station_load)

with st.container(border=True):
    st.write('其他类型负荷')
    tab1, tab2, tab3, tab4 = st.tabs(["年", "季", "月", "日"])
    with tab1:
        uploaded_files = st.file_uploader(
            "其他类型按年", accept_multiple_files=True, label_visibility='collapsed'
        )
        for uploaded_file in uploaded_files:
            stringio = StringIO(uploaded_file.getvalue().decode("utf-8"))
            dataframe = pd.read_csv(uploaded_file)
            st.write(dataframe)

    with tab2:
        uploaded_files = st.file_uploader(
            "其他类型按季", accept_multiple_files=True, label_visibility='collapsed'
        )
        for uploaded_file in uploaded_files:
            stringio = StringIO(uploaded_file.getvalue().decode("utf-8"))
            dataframe = pd.read_csv(uploaded_file)
            st.write(dataframe)

    with tab3:
        uploaded_files = st.file_uploader(
            "其他类型按月", accept_multiple_files=True, label_visibility='collapsed'
        )
        for uploaded_file in uploaded_files:
            stringio = StringIO(uploaded_file.getvalue().decode("utf-8"))
            dataframe = pd.read_csv(uploaded_file)
            st.write(dataframe)

    with tab4:
        uploaded_files = st.file_uploader(
            "其他类型按天", accept_multiple_files=True, label_visibility='collapsed'
        )
        for uploaded_file in uploaded_files:
            stringio = StringIO(uploaded_file.getvalue().decode("utf-8"))
            dataframe = pd.read_csv(uploaded_file)
            st.write(dataframe)

    energy_capacity = st.sidebar.number_input("储能功率kW")

    storage_duration_hours = st.sidebar.number_input("储能时长h")

    storage_efficiency = st.sidebar.number_input("储能效率%")
    storage_capacity = energy_capacity * storage_duration_hours

with st.container(border=True):
    st.write('光伏输出')
    pv_hourly_generation_year_25 = pv_hourly_generation_year_0.copy()

    column_name = 'generation'
    # 检查是否存在该列
    if column_name in pv_hourly_generation_year_0.columns:

        # 使用乘法运算符 * 来乘以整个列
        pv_hourly_generation_year_25[column_name] = pv_hourly_generation_year_0[column_name] * (
                1 - first_year_decay) * ((1 - multi_year_decay) ** 24)
        st.write('光伏25年每小时发电量', pv_hourly_generation_year_25)
    else:
        print(f"列 '{column_name}' 不存在于数据框中。请检查您的CSV文件和列名。")
    fig = px.line(pv_hourly_generation_year_0, x='id', y='generation',
                  title='光伏0年每小时发电量',
                  labels={
                  })
    fig.update_xaxes(nticks=24)
    fig.update_layout(
        xaxis_title=None
    )
    st.plotly_chart(fig)
    fig = px.line(pv_hourly_generation_year_25, x='id', y='generation',
                  title='光伏25年每小时发电量',
                  labels={
                  })
    st.plotly_chart(fig)

with st.container(border=True):
    st.write('负荷输出')

    fig = px.line(business_load, x='id', y='generation',
                  title='工商业负荷',
                  labels={
                  })
    # fig.update_xaxes(nticks=24)
    # fig.update_layout(
    #     xaxis_title=None
    # )
    st.plotly_chart(fig)
    fig = px.line(charging_station_load, x='id', y='generation',
                  title='充电桩负荷',
                  labels={
                  })
    st.plotly_chart(fig)
    fig = px.line(charging_station_load + business_load, x='id', y='generation',
                  title='合成负荷',
                  labels={
                  })
    st.plotly_chart(fig)

    # 定义基础代理购电价格和平段价格
    base_purchase_price = 0.2855
    fixed_cost = 0.122325

    # 计算平段价格
    normal_price = base_purchase_price + fixed_cost

    # 定义不同时段的浮动比例
    float_rates = {
        'big_wind_season': {
            'peak': 0.68,  # 高峰时段上浮68%
            'valley': -0.52  # 谷段下浮52%
        },
        'small_wind_season': {
            'peak': 0.54,  # 高峰时段上浮54%
            'valley': -0.56  # 谷段下浮56%
        }
    }

    # 尖峰和深谷时段的额外浮动比例
    sharp_peak_float = 0.20  # 尖峰时段上浮20%
    deep_valley_float = -0.20  # 深谷时段下浮20%


    # 定义时段
    def get_price_period(hour, month):
        if 1 <= month <= 5 or 9 <= month <= 12:  # 大风季
            season = 'big_wind_season'
            if 6 <= hour < 8 or 18 <= hour < 22:
                return 'peak', season, False  # 第三个参数表示是否为尖峰或深谷时段
            elif 4 <= hour < 6 or 8 <= hour < 11 or 16 <= hour < 18 or 22 <= hour < 24:
                return 'normal', season, False
            else:
                return 'valley', season, False
        elif 6 <= month <= 8:  # 小风季
            season = 'small_wind_season'
            if 19 <= hour < 21:  # 尖峰时段
                return 'peak', season, True
            elif 13 <= hour < 15:  # 深谷时段
                return 'valley', season, True
            elif 6 <= hour < 8 or 18 <= hour < 19 or 21 <= hour < 22:
                return 'peak', season, False
            elif 0 <= hour < 6 or 8 <= hour < 11 or 16 <= hour < 18 or 22 <= hour < 24:
                return 'normal', season, False
            else:
                return 'valley', season, False
        else:
            raise ValueError("Month should be between 1 and 12")


    # 创建日期时间索引
    date_range = pd.date_range(start='2024-01-01', end='2024-12-31 23:00:00', freq='h')

    # 初始化电价列表
    price_list = []

    # 计算每个小时的电价
    for dt in date_range:
        period, season, is_special = get_price_period(dt.hour, dt.month)

        if period == 'normal':
            price = normal_price
        else:
            float_rate = float_rates[season][period]
            if is_special:
                if period == 'peak':  # 尖峰时段
                    float_rate += sharp_peak_float
                elif period == 'valley':  # 深谷时段
                    float_rate += deep_valley_float

            price = base_purchase_price * (1 + float_rate) + fixed_cost

        price_list.append(price)

    # 创建DataFrame
    df_prices_xi = pd.DataFrame({
        'datetime': date_range,
        'price': price_list
    })

    # 设置datetime为索引
    df_prices_xi.set_index('datetime', inplace=False)

    # 打印前几行以检查结果
    # print(df_prices.head())

    # 如果需要保存到CSV文件
    # df_prices.to_csv('hourly_prices_2024.csv')
    fig = px.line(df_prices_xi, x='datetime', y='price',
                  title='蒙西电价',
                  labels={
                  })
    st.plotly_chart(fig)

    # 定义基础代理购电价格和平段价格（第二个地方）
    base_purchase_price = 0.221850
    fixed_cost = 0.22281

    # 计算平段价格
    normal_price = base_purchase_price + fixed_cost

    # 定义不同时段的浮动比例
    float_rates = {
        'peak': 0.68,  # 高峰时段上浮68%
        'valley': -0.52  # 谷段下浮52%
    }

    # 尖峰和深谷时段的额外浮动比例
    sharp_peak_float = 0.20  # 尖峰时段上浮20%
    deep_valley_float = -0.20  # 深谷时段下浮20%


    # 定义时段
    def get_price_period(hour, month):
        if 1 <= month <= 5 or 9 <= month <= 12:  # 大风季
            if 6 <= hour < 9 or 17 <= hour < 22:
                return 'peak', False  # 第二个参数表示是否为尖峰或深谷时段
            elif 5 <= hour < 6 or 9 <= hour < 11 or 14 <= hour < 17 or 22 <= hour < 24:
                return 'normal', False
            else:
                return 'valley', False
        elif 6 <= month <= 8:  # 小风季
            if 18 <= hour < 20:  # 尖峰时段
                return 'peak', True
            elif 12 <= hour < 14:  # 深谷时段
                return 'valley', True
            elif 6 <= hour < 9 or 17 <= hour < 18 or 20 <= hour < 22:
                return 'peak', False
            elif 5 <= hour < 6 or 9 <= hour < 11 or 14 <= hour < 17 or 22 <= hour < 24:
                return 'normal', False
            else:
                return 'valley', False
        else:
            raise ValueError("Month should be between 1 and 12")


    # 创建日期时间索引
    date_range = pd.date_range(start='2024-01-01', end='2024-12-31 23:00:00', freq='h')

    # 初始化电价列表
    price_list = []

    # 计算每个小时的电价
    for dt in date_range:
        period, is_special = get_price_period(dt.hour, dt.month)

        if period == 'normal':
            price = normal_price
        else:
            float_rate = float_rates[period]
            if is_special:
                if period == 'peak':  # 尖峰时段
                    float_rate += sharp_peak_float
                elif period == 'valley':  # 深谷时段
                    float_rate += deep_valley_float

            price = base_purchase_price * (1 + float_rate) + fixed_cost

        price_list.append(price)

    # 创建DataFrame
    df_prices_dong = pd.DataFrame({
        'datetime': date_range,
        'price': price_list
    })

    # 设置datetime为索引
    df_prices_dong.set_index('datetime', inplace=False)
    fig = px.line(df_prices_dong, x='datetime', y='price',
                  title='蒙东电价',
                  labels={
                  })
    st.plotly_chart(fig)

with st.container(border=True):
    st.title('生产模拟')
    st.write('分布式光伏市场化项目')

    option = st.selectbox(
        "How would you like to be contacted?",
        ("蒙西", "蒙东"),
    )

    pv_hourly_generation_year_0 = pd.DataFrame({'generation': np.random.uniform(100, 1500, 8760)})
    business_load = pd.DataFrame({'generation': np.random.uniform(100, 1000, 8760)})


    def get_period_type(hour, month, option=1):
        if option == '蒙东':
            if month in [1, 2, 3, 4, 5, 9, 10, 11, 12]:  # 大风季
                if 6 <= hour < 8 or 18 <= hour < 22:
                    return 'peak'
                elif (4 <= hour < 6 or 8 <= hour < 11 or 16 <= hour < 18 or 22 <= hour < 24):
                    return 'flat'
                else:
                    return 'valley'
            elif month in [6, 7, 8]:  # 小风季
                if 6 <= hour < 8 or 18 <= hour < 22:
                    return 'peak'
                elif (0 <= hour < 6 or 8 <= hour < 11 or 16 <= hour < 18 or 22 <= hour < 24):
                    return 'flat'
                else:
                    return 'valley'
            else:
                raise ValueError("Invalid month")
        elif option == '蒙西':
            if 6 <= hour < 9 or 17 <= hour < 22:
                return 'peak'
            elif (5 <= hour < 6 or 9 <= hour < 11 or 14 <= hour < 17 or 22 <= hour < 24):
                return 'flat'
            else:
                return 'valley'
        else:
            raise ValueError("Invalid option")


    difference = pv_hourly_generation_year_0['generation'] - business_load['generation']

    # 初始化储能状态
    storage_level_1 = [0]  # 假设储能初始状态为0
    storage_level_2 = [0]
    charge_rate = 100  # 充电速率（单位：每小时）
    discharge_rate = storage_efficiency * charge_rate / 100  # 放电速率（单位：每小时）
    min_storage = 0  # 最小储能容量
    discarded_energy = [0]
    date_range = pd.date_range(start='2023-01-01', periods=8760, freq='h')
    pv_hourly_generation_year_0.index = date_range
    business_load.index = date_range
    st.write('方案一')
    # 计算每天的储能变化
    for i, diff in enumerate(difference[:-1]):  # 我们已经初始化了第一个元素，所以从第二个开始
        last_storage = storage_level_1[-1]
        hour = date_range[i].hour
        month = date_range[i].month
        period_type = get_period_type(hour, month, option)

        if diff > 0:  # 发电量大于负荷，储能充电
            potential_new_storage = last_storage + charge_rate
            if potential_new_storage > storage_capacity:
                new_storage = storage_capacity
                # 计算舍弃的电量
                excess_energy = potential_new_storage - storage_capacity
                discarded_energy.append(excess_energy)
                # st.write(potential_new_storage,storage_capacity,excess_energy)
            else:
                new_storage = potential_new_storage
                discarded_energy.append(0)  # 没有超过最大容量，舍弃电量为0
        elif period_type == 'peak' and last_storage > 0:  # 发电量小于负荷，储能放电
            new_storage = max(last_storage - discharge_rate, min_storage)
            discarded_energy.append(0)
        else:
            new_storage = last_storage  # 发电量等于负荷，储能不变
            discarded_energy.append(0)
        storage_level_1.append(new_storage)

    # 将储能水平转换为DataFrame
    storage_df = pd.DataFrame(storage_level_1, columns=['Storage'])
    st.line_chart(storage_df)

    pv_hourly_generation_year_0['discarded_energy_series'] = discarded_energy
    pv_hourly_generation_year_0['discarded_ratio'] = discarded_energy / pv_hourly_generation_year_0[
        'generation']

    st.write(pv_hourly_generation_year_0)
    st.line_chart(pv_hourly_generation_year_0['discarded_ratio'])
    average_discarded_ratio = pv_hourly_generation_year_0['discarded_ratio'].mean()
    st.write(average_discarded_ratio)
    st.write('方案二')
    # 计算每天的储能变化
    discarded_energy = [0]
    for i, diff in enumerate(difference[:-1]):
        last_storage = storage_level_2[-1]

        if diff > 0:  # 发电量大于负荷，储能充电
            potential_new_storage = last_storage + charge_rate
            if potential_new_storage > storage_capacity:
                new_storage = storage_capacity
                # 计算舍弃的电量
                excess_energy = potential_new_storage - storage_capacity
                discarded_energy.append(excess_energy)
            else:
                new_storage = potential_new_storage
                discarded_energy.append(0)  # 没有超过最大容量，舍弃电量为0
        elif diff < 0:  # 发电量小于负荷，储能放电
            new_storage = max(last_storage - discharge_rate, min_storage)
            discarded_energy.append(0)  # 放电时不涉及舍弃电量
        else:  # 发电量等于负荷，储能不变
            new_storage = last_storage
            discarded_energy.append(0)  # 没有充放电，舍弃电量为0

        storage_level_2.append(new_storage)

    storage_df = pd.DataFrame(storage_level_2, columns=['Storage'])
    st.line_chart(storage_df)
    # 将储能水平转换为DataFrame
    pv_hourly_generation_year_0['discarded_energy_series'] = discarded_energy
    pv_hourly_generation_year_0['discarded_ratio'] = discarded_energy / pv_hourly_generation_year_0[
        'generation']
    st.write(pv_hourly_generation_year_0)
    st.line_chart(pv_hourly_generation_year_0['discarded_ratio'])
    average_discarded_ratio = pv_hourly_generation_year_0['discarded_ratio'].mean()
    st.write(average_discarded_ratio)
with st.container(border=True):
    st.title('生产模拟')
    st.write('“光储充”一体化项目')

if "uploaded_file" in st.session_state:
    processed_file = st.session_state.uploaded_file
    if processed_file is not None:
        df = processed_file

        st.title("区间数据")
        # 输入条件
        st.sidebar.subheader('输入条件')
        start_date = st.sidebar.date_input("开始日期", datetime.date(2023, 6, 23))
        end_date = st.sidebar.date_input("结束日期", datetime.date(2024, 6, 22))
        df["日期"] = pd.to_datetime(df["日期"])
        mask = (df["日期"].dt.date >= start_date) & (df["日期"].dt.date <= end_date)
        filtered_df = df[mask]
        mask = (df["日期"].dt.date >= datetime.date(2023, 6, 1)) & (
                df["日期"].dt.date <= datetime.date(2024, 5, 31))
        filtered_df_23 = df[mask]
        names = list(df.keys())
        node_names = names[5:]
        all_names = names[3:]
        area = st.sidebar.selectbox("选择区域", (names[3], names[4]))
        city = st.sidebar.selectbox(
            "选择地区",
            ("包头市", "鄂尔多斯市", "阿拉善盟", "锡林郭勒盟", "呼和浩特市", "乌海市", "巴彦淖尔市", "乌兰察布市"),
            index=None,
            # placeholder="Select contact method...",
        )
        if city == "包头市":
            node = st.sidebar.selectbox("选择节点", names[5:37])
        elif city == "鄂尔多斯市":
            node = st.sidebar.selectbox("选择节点", names[37:74])
        elif city == "阿拉善盟":
            node = st.sidebar.selectbox("选择节点", names[74:89])
        elif city == "锡林郭勒盟":
            node = st.sidebar.selectbox("选择节点", names[89:110])
        elif city == "呼和浩特市":
            node = st.sidebar.selectbox("选择节点", names[110:140])
        elif city == "乌海市":
            node = st.sidebar.selectbox("选择节点", names[140:154])
        elif city == "巴彦淖尔市":
            node = st.sidebar.selectbox("选择节点", names[154:179])
        elif city == "乌兰察布市":
            node = st.sidebar.selectbox("选择节点", names[179:214])
        else:
            node = st.sidebar.selectbox("选择节点", node_names)
        option = {
            "电网侧储能": 16,
            "电源侧储能": 8
        }
        reserve_type = st.sidebar.selectbox("储能类型",
                                            list(option.keys()),
                                            # index=None,
                                            # placeholder="选择储能类型...",
                                            )
        efficiency = st.sidebar.number_input("储能效率", value=0.85, placeholder="输入储能效率...")
        reserve_speed = st.sidebar.number_input("储能功率(MW)", value=100, placeholder="输入储能功率...")
        reserve_capacity = reserve_speed * option[reserve_type] / 4
        tariff = st.sidebar.number_input("输配电价(元/kWh)", value=0.0455, format="%f")
        other = st.sidebar.number_input("政府性资金及附加(元/kWh)", value=0.022425, format="%f")
        others = tariff + other
        on = st.sidebar.checkbox("是否纳入示范项目")
        if on:
            subsidy = st.sidebar.number_input("补偿标准（元/kWh）", value=0.35, format="%f")

        # 电价数据
        with st.container(border=True):
            st.subheader('电价数据', divider=True)
            df_show = df
            df_show.index = df['日期+时刻']

            if st.checkbox('显示数据'):
                st.dataframe(df_show, use_container_width=True)
            with st.container(border=True):
                options1 = st.multiselect("选择", all_names, [area, node])
                fig = px.line(filtered_df, x="日期+时刻", y=options1, title="电价数据", template='plotly_white')
                fig.update_traces(textposition="bottom right")
                fig.update_layout(
                    xaxis_title=None,
                    yaxis_title="电价（元/MWh）",
                    margin=dict(b=150),  # 调整边距
                    height=600
                )
                fig.update_xaxes(
                    tickformat="%Y-%m-%d"  # 设置日期格式为年-月-日
                )
                st.plotly_chart(fig, theme="streamlit", use_container_width=True)

        with st.container(border=True):
            tab1, tab2, tab3 = st.tabs(["一充一放", "多充多放", "随充随放"])
            with tab1:
                st.subheader('逐日收益', divider=True)
                expander = st.expander("查看计算方法")
                expander.write(
                    '''
                    每天都不固定时间（最长为2小时或4小时，以收益最大为标准）充放电一次，如果收益为负，则放弃充放电
                    ''')
                tab1_1 = []
                tab1_2 = []
                tab1_3 = []
                tab1_4 = []
                tab1_5 = []
                tab1_6 = []
                tab1_7 = []
                daily_gains = filtered_df.groupby(filtered_df['日期'].dt.date).apply(
                    lambda group: calculate_daily_gain(option[reserve_type], group, tab1_1, tab1_2, tab1_3, tab1_4,
                                                       tab1_5, tab1_6, tab1_7))

                st.write("区间总收益：", round(daily_gains.sum() / 10000, 4), "（万元）")
                daily_gains_df = daily_gains.reset_index()
                daily_gains_df.columns = ['日期', '收益（元）']
                fig = px.line(daily_gains_df, x="日期", y="收益（元）", markers=True, title="逐日收益")
                fig.update_traces(textposition="bottom right")
                fig.update_xaxes(
                    tickformat="%Y-%m-%d"  # 设置日期格式为年-月-日
                )
                fig.update_layout(
                    xaxis_title=None
                )
                st.plotly_chart(fig, theme="streamlit", use_container_width=True)

                st.subheader('区间总放电量', divider=True)
                st.write("区间总放电量：", sum(tab1_2), "（MWh）")
                st.write("每日平均放电量：", round(sum(tab1_2) / len(tab1_2), 1), "（MWh）")
                st.write("弃电天数：", tab1_2.count(0))
                tab1_1 = pd.DataFrame(tab1_1)
                tab1_1["放电量（MWh）"] = tab1_2
                tab1_1["充电量（MWh）"] = tab1_3
                tab1_1.columns = ['日期', '放电量（MWh）', '充电量（MWh）']
                tab1_1.index += 1
                st.dataframe(tab1_1)

                if tab1_4:
                    tab1_4 = pd.DataFrame(tab1_4)
                    tab1_4["充电电价"] = tab1_5
                    tab1_4.columns = ['充电时间', '充电电价']
                    tab1_4.index += 1
                    st.dataframe(tab1_4)
                if tab1_6:
                    tab1_6 = pd.DataFrame(tab1_6)
                    tab1_6["放电电价"] = tab1_7
                    tab1_6.columns = ['放电时间', '放电电价']
                    tab1_6.index += 1
                    st.dataframe(tab1_6)
            with tab2:
                st.subheader('逐日收益', divider=True)
                expander = st.expander("查看计算方法")
                expander.write(
                    '''
                    每次充放电都以最大时间（4小时或2小时）为单位，采取最适合的充放电策略使得收益最大
                    ''')

                tab2_1 = []
                tab2_2 = []
                tab2_3 = []
                tab2_4 = []
                tab2_5 = []
                tab2_6 = []
                tab2_7 = []
                tab2_8 = []
                max_profit_value, operations = max_profit_more(filtered_df, option[reserve_type])
                st.write("区间总收益：", round(max_profit_value / 10000, 4), "（万元）")

                # 逐日收益
                filtered_df.insert(loc=len(filtered_df.columns), column='op1', value=operations)
                max_profit_value = filtered_df.groupby(filtered_df['日期'].dt.date).apply(
                    lambda group: max_daily_profit(group, 1, "op1", tab2_1, tab2_2, tab2_3,
                                                   tab2_4, tab2_5,
                                                   tab2_6, tab2_7, tab2_8)
                )
                tab2_1 = pd.DataFrame(tab2_1)
                tab2_1["放电量（MWh）"] = tab2_2
                tab2_1["充电量（MWh）"] = tab2_3
                tab2_1["充放电次数"] = tab2_8
                tab2_1.columns = ['日期', '放电量（MWh）', '充电量（MWh）', '充放电次数']
                tab2_1.index += 1

                max_profit_value = max_profit_value.reset_index()
                max_profit_value.columns = ['日期', '收益（元）']

                fig = px.line(max_profit_value, x="日期", y="收益（元）", markers=True, title="逐日收益")
                fig.update_traces(textposition="bottom right")
                fig.update_xaxes(
                    tickformat="%Y-%m-%d"  # 设置日期格式为年-月-日
                )
                fig.update_layout(
                    xaxis_title=None
                )
                st.plotly_chart(fig, theme="streamlit", use_container_width=True)
                st.subheader('区间总放电量', divider=True)
                st.write("区间总放电量：", tab2_1['放电量（MWh）'].sum(), "（MWh）")
                st.write("每日平均放电量：", round(tab2_1['放电量（MWh）'].mean(), 1), "（MWh）")
                fig = px.line(tab2_1, x="日期", y="放电量（MWh）", markers=True, title="放电量")
                fig.update_xaxes(
                    tickformat="%Y-%m-%d"  # 设置日期格式为年-月-日
                )
                fig.update_layout(
                    xaxis_title=None
                )
                st.plotly_chart(fig, theme="streamlit", use_container_width=True)
                st.dataframe(tab2_1)

                if tab2_4:  # 如果 tab2_4 不为空
                    tab2_4 = pd.DataFrame(tab2_4)
                    tab2_4["充电电价"] = tab2_5
                    tab2_4.columns = ['充电时间', '充电电价']
                    tab2_4.index += 1
                    st.dataframe(tab2_4)

                if tab2_6:  # 如果 tab2_6 不为空
                    tab2_6 = pd.DataFrame(tab2_6)
                    tab2_6["放电电价"] = tab2_7
                    tab2_6.columns = ['放电时间', '放电电价']
                    tab2_6.index += 1
                    st.dataframe(tab2_6)

            with tab3:
                # 区间总收益动态规划算法
                st.subheader('逐日收益', divider=True)
                expander = st.expander("查看计算方法")
                expander.write(
                    '''
                    每次充放电都以最小时间为单位（15分钟），采取最适合的充放电策略使得收益最大
                    ''')
                tab3_1 = []
                tab3_2 = []
                tab3_3 = []
                tab3_4 = []
                tab3_5 = []
                tab3_6 = []
                tab3_7 = []
                tab3_8 = []
                max_profit_value, operations = max_profit(filtered_df, option[reserve_type])

                st.write("区间总收益：", round(max_profit_value / 10000, 4), "（万元）")

                # 逐日收益
                filtered_df.insert(loc=len(filtered_df.columns), column='op', value=operations)

                max_profit_value = filtered_df.groupby(filtered_df['日期'].dt.date).apply(
                    lambda group: max_daily_profit(group, option[reserve_type], 'op', tab3_1, tab3_2, tab3_3,
                                                   tab3_4, tab3_5, tab3_6, tab3_7, tab3_8)
                )
                tab3_1 = pd.DataFrame(tab3_1)
                tab3_1["放电量（MWh）"] = tab3_2
                tab3_1["充电量（MWh）"] = tab3_3
                tab3_1["充放电次数"] = tab3_8
                tab3_1.columns = ['日期', '放电量（MWh）', '充电量（MWh）', '充放电次数']
                tab3_1.index += 1

                max_profit_value = max_profit_value.reset_index()
                max_profit_value.columns = ['日期', '收益（元）']

                fig = px.line(max_profit_value, x="日期", y="收益（元）", markers=True, title="逐日收益")
                fig.update_traces(textposition="bottom right")
                fig.update_xaxes(
                    tickformat="%Y-%m-%d"  # 设置日期格式为年-月-日
                )
                fig.update_layout(
                    xaxis_title=None
                )
                st.plotly_chart(fig, theme="streamlit", use_container_width=True)
                st.subheader('区间总放电量', divider=True)
                st.write("区间总放电量：", tab3_1['放电量（MWh）'].sum(), "（MWh）")
                st.write("每日平均放电量：", round(tab3_1['放电量（MWh）'].mean(), 1), "（MWh）")
                fig = px.line(tab3_1, x="日期", y="放电量（MWh）", markers=True, title="放电量")
                fig.update_xaxes(
                    tickformat="%Y-%m-%d"  # 设置日期格式为年-月-日
                )
                fig.update_layout(
                    xaxis_title=None
                )
                st.plotly_chart(fig, theme="streamlit", use_container_width=True)
                st.dataframe(tab3_1)

                if tab3_4:
                    from datetime import datetime, time as dt_time

                    tab3_4 = [datetime.strptime(date_str, '%Y/%m/%d %H:%M') for date_str in tab3_4]

                    # 创建DataFrame
                    tab3_4 = pd.DataFrame(tab3_4, columns=['DateTime'])
                    tab3_4["充电电价"] = tab3_5

                    # 提取时间部分并应用函数计算Count列

                    tab3_4['Count'] = tab3_4['DateTime'].apply(calculate_count)
                    tab3_4.columns = ['充电时间', '充电电价', '节点']
                    tab3_4.index += 1
                    st.dataframe(tab3_4)
                    fig = px.line(tab3_4, x="充电时间", y="充电电价")
                    st.plotly_chart(fig, theme="streamlit", use_container_width=True)
                if tab3_6:
                    from datetime import datetime, time as dt_time

                    tab3_6 = [datetime.strptime(date_str, '%Y/%m/%d %H:%M') for date_str in tab3_6]

                    tab3_6 = pd.DataFrame(tab3_6, columns=['DateTime'])
                    tab3_6["放电电价"] = tab3_7
                    tab3_6['Count'] = tab3_6['DateTime'].apply(calculate_count)
                    tab3_6.columns = ['放电时间', '放电电价', '节点']
                    tab3_6.index += 1
                    st.dataframe(tab3_6)
                    fig = px.line(tab3_6, x="放电时间", y="放电电价")
                    st.plotly_chart(fig, theme="streamlit", use_container_width=True)
        # 逐日充放电最大价差
        with st.container(border=True):
            st.subheader('逐日充放电最大价差', divider=True)
            daily_diffs = filtered_df.groupby(filtered_df['日期'].dt.date).apply(
                lambda group: group[node].max() - group[area].min()
            )
            st.write("平均充放电价差：", round(daily_diffs.mean(), 1), '（元/MWh）')
            daily_diffs_df = daily_diffs.reset_index()
            daily_diffs_df.columns = ['日期', '差价（元/MWh）']
            fig = px.line(daily_diffs_df, x="日期", y="差价（元/MWh）", title="逐日充放电最大价差")
            fig.update_traces(textposition="bottom right")
            fig.update_xaxes(
                tickformat="%Y-%m-%d"  # 设置日期格式为年-月-日
            )
            fig.update_layout(
                xaxis_title=None
            )
            st.plotly_chart(fig, theme="streamlit", use_container_width=True)
            st.dataframe(daily_diffs_df)

        # 节点、区域逐日平均数据
        with st.container(border=True):
            st.subheader('逐日平均数据', divider=True)
            options2 = st.multiselect("选择区域节点", all_names, [area, node])
            daily = filtered_df.groupby(filtered_df['日期'].dt.date).apply(
                lambda group: group[options2].mean()
            )
            daily_df = daily.reset_index()
            fig = px.line(daily_df, x="日期", y=options2, title="逐日平均数据", template='plotly_white')
            fig.update_traces(textposition="bottom right")
            fig.update_layout(
                xaxis_title=None,
                yaxis_title="电价（元/MWh）",
            )
            fig.update_xaxes(
                tickformat="%Y-%m-%d"  # 设置日期格式为年-月-日
            )
            st.plotly_chart(fig, theme="streamlit", use_container_width=True)

        with st.container(border=True):

            st.subheader('节点数据汇总', divider=True)
            city = st.selectbox(
                "选择城市",
                ("包头市", "鄂尔多斯市", "阿拉善盟", "锡林郭勒盟", "呼和浩特市", "乌海市", "巴彦淖尔市",
                 "乌兰察布市"),
                index=None,
                # placeholder="Select contact method...",
            )

            if st.button("计算"):
                tab4_1 = []
                tab4_2 = []
                tab4_3 = []
                tab4_4 = []
                tab4_5 = []
                tab4_6 = []
                tab4_7 = []
                tab4_8 = []
                tab4_9 = []
                tab4_10 = []
                tab4_11 = []
                node_temp = node
                if city == "包头市":
                    range_to_process = range(5, 37)
                elif city == "鄂尔多斯市":
                    range_to_process = range(37, 74)
                elif city == "阿拉善盟":
                    range_to_process = range(74, 89)
                elif city == "锡林郭勒盟":
                    range_to_process = range(89, 110)
                elif city == "呼和浩特市":
                    range_to_process = range(110, 140)
                elif city == "乌海市":
                    range_to_process = range(140, 154)
                elif city == "巴彦淖尔市":
                    range_to_process = range(154, 179)
                elif city == "乌兰察布市":
                    range_to_process = range(179, 214)
                for i in range_to_process:
                    tab4_1.clear()
                    tab4_2.clear()
                    tab4_3.clear()
                    node = names[i]
                    tab4_10.append(names[i])
                    max_profit_value, operations = max_profit_more(filtered_df, option[reserve_type])

                    tab4_9.append(round(max_profit_value / 10000, 4))
                    # 逐日收益
                    filtered_df.insert(loc=len(filtered_df.columns), column=i, value=operations)
                    max_profit_value = filtered_df.groupby(filtered_df['日期'].dt.date).apply(
                        lambda group: max_daily_profit(group, option[reserve_type], 'op', tab4_1, tab4_2, tab4_3,
                                                       tab4_4, tab4_5, tab4_6, tab4_7, tab4_8)
                    )
                    tab4_11.append(sum(tab4_2))

                tab4_10 = pd.DataFrame(tab4_10)
                tab4_10["区间总收益"] = tab4_9
                tab4_10["区间总放电量"] = tab4_11
                tab4_10.columns = ['节点', '区间总收益(万元)', '区间总放电量(MWh)']

                tab4_10 = tab4_10.sort_values(by='区间总收益(万元)', ascending=False)
                tab4_10 = tab4_10.reset_index(drop=True)
                tab4_10.index += 1
                fig = px.bar(tab4_10, x="节点", y='区间总收益(万元)', title="节点汇总",
                             barmode="group")

                fig.update_layout(
                    xaxis_title=None
                )
                st.plotly_chart(fig, theme="streamlit", use_container_width=True)
                st.dataframe(tab4_10)
                node = node_temp


